package hotciv.standard;

import java.awt.Color;
import java.awt.Point;
import java.util.HashMap;
import java.util.Iterator;

import javax.swing.JTextField;

import minidraw.framework.Drawing;
import minidraw.framework.DrawingEditor;
import minidraw.framework.Figure;
import minidraw.standard.ImageFigure;
import minidraw.standard.StandardDrawing;
import hotciv.framework.*;
import hotciv.view.CityFigure;
import hotciv.view.GfxConstants;
import hotciv.view.TextFigure;
import hotciv.view.UnitFigure;

public class GameObserverImpl extends StandardDrawing implements GameObserver
{
	//TODO make all private
	protected int age = -4000;
	protected Player nextPlayer = Player.RED;
	protected Unit lastUnitDestroyed;
	protected Unit lastUnitCreated;
	protected Unit unitMoved;
	protected City lastCityCreated;
	protected City lastCityChanged;
	protected Position positionLastUnitDestroyed;
	protected Position lastUnitCreatedPosition;
	protected Position lastCityCreatedPosition;
	protected Position lastCityChangedPosition;
	protected Position unitMovedFrom;
	protected Position unitMovedTo;
	protected DrawingEditor editor;
	
	private TextFigure produceField;
	private TextFigure balanceField;
	private TextFigure moveCountField;
	private ImageFigure turnShieldIcon;
	protected Game game;
	
	private HashMap<Unit, Figure> unitFigureMap= new HashMap<Unit, Figure>();

	private HashMap<City, Figure> cityFigureMap= new HashMap<City, Figure>();
	
	public GameObserverImpl(DrawingEditor editor, Game g)
	{
		super();
		this.editor=editor;
		game = g;
		game.addObserver(this);
		defineUnitMap();
		defineIcons();
	}
	
	private void defineUnitMap() 
	{
		 clearSelection();

		 Position p;
		 
		 for ( int r = 0; r < GameConstants.WORLDSIZE; r++ ) 
		 {
			 for ( int c = 0; c < GameConstants.WORLDSIZE; c++ ) 
			 {
		        p = new Position(r,c);
		        
		        City city = game.getCityAt(p);
		        if ( city != null ) 
		        {
		         // convert the unit's Position to (x,y) coordinates
		          Point point = new Point( GfxConstants.getXFromColumn(p.getColumn()),
		                                   GfxConstants.getYFromRow(p.getRow()) );
		          CityFigure cityFigure = new CityFigure(city, point);
		          cityFigure.addFigureChangeListener(this);

		          cityFigureMap.put(city, cityFigure);
		          // also insert in superclass list as it is
		          // this list that is iterated by the
		          // graphics rendering algorithms
		          super.add(cityFigure);
		        }
		        
		        Unit unit = game.getUnitAt(p);
		        if ( unit != null ) 
		        {
		          String type = unit.getTypeString();
		          // convert the unit's Position to (x,y) coordinates
		          Point point = new Point( GfxConstants.getXFromColumn(p.getColumn()), GfxConstants.getYFromRow(p.getRow()) );
		          UnitFigure unitFigure = new UnitFigure( type, point, unit );
		          unitFigure.addFigureChangeListener(this);

		          unitFigureMap.put(unit, unitFigure);
		          // also insert in superclass list as it is
		          // this list that is iterated by the
		          // graphics rendering algorithms
		          super.add(unitFigure);
		        }
		      }
		    }
		
	}

	@Override
	public void cityChanged(City city, Position position)
	{
		lastCityChanged = city;
		
		if(city.getOwner()==Player.RED)
		{
			cityFigureMap.remove(city);
			lastCityChanged.setOwner(Player.RED);
			cityFigureMap.put(lastCityChanged, createCityFigure(lastCityChanged, position));
		}
		else
		{
			cityFigureMap.remove(city);
			lastCityChanged.setOwner(Player.BLUE);
			cityFigureMap.put(lastCityChanged, createCityFigure(lastCityChanged, position));
		}
		super.requestUpdate();
	}
	
	@Override
	public void cityCreated(City city, Position position) 
	{
		Figure cityFigure = createCityFigure(city, position);
		cityFigureMap.put(city, cityFigure);	
		super.add(cityFigure);
		super.requestUpdate();
	}

	@Override
	public void tileFocusChanged(Position position) 
	{
		Figure thisFigure = super.findFigure(GfxConstants.getXFromColumn(position.getColumn()), GfxConstants.getYFromRow(position.getRow()));
		if(cityFigureMap.containsValue(thisFigure)) //our figure is a city
		{
			int balance = game.getCityAt(position).getTreasury();
			String produce = game.getCityAt(position).getProduction();
			
			super.addToSelection(thisFigure);
			balanceField.setText(""+balance);
			produceField.setText(produce);
			
		}	
		if(unitFigureMap.containsValue(thisFigure))
		{
			Unit u = game.getUnitAt(position);
			moveCountField.setText(""+u.getMoveCount());
		}
		super.requestUpdate();
	}

	@Override
	public void turnEnds(Player nextPlayer, int age) 
	{
		this.nextPlayer = nextPlayer;
		this.age = age;

		String playerName = "red";
		if(nextPlayer == Player.BLUE) playerName="blue"; 
		turnShieldIcon.set(playerName+"shield",
                new Point( GfxConstants.TURN_SHIELD_X,
                           GfxConstants.TURN_SHIELD_Y ) );
	}
	
	@Override
	public void unitCreated(Unit unit, Position position) 
	{
		Figure unitFigure = createUnitFigure(unit, position);
		unitFigureMap.put(unit, unitFigure);
		super.add(unitFigure);
		super.requestUpdate();
	}

	@Override
	public void unitDestroyed(Unit unit, Position position) 
	{
		super.remove(unitFigureMap.get(unit));
		unitFigureMap.remove(unit);
		super.requestUpdate();
	}

	@Override
	public void unitMoved(Unit unit, Position from, Position to)
	{		
		super.removeFromSelection(unitFigureMap.get(unit));
		
		super.remove(unitFigureMap.get(unit));
		
		unitFigureMap.remove(unit);
		
		unitFigureMap.put(unit, createUnitFigure(unit, to));
		
		super.add(unitFigureMap.get(unit));
		
		unitFigureMap.get(unit).addFigureChangeListener(this);
		
		super.requestUpdate();
	}
	
	private UnitFigure createUnitFigure(Unit u, Position p)
	{
		String type = u.getTypeString();
		Point point = new Point(GfxConstants.getXFromColumn(p.getColumn()), GfxConstants.getYFromRow(p.getRow()));
		return new UnitFigure(type, point, u);
	}


	private CityFigure createCityFigure(City c, Position p)
	{
		Point point = new Point(GfxConstants.getXFromColumn(p.getColumn()), GfxConstants.getYFromRow(p.getRow()));
		return new CityFigure(c, point);
	}
	
	private void defineIcons() {
	    // very much a template implementation :)
	    turnShieldIcon = 
	      new ImageFigure( "redshield",
	                       new Point( GfxConstants.TURN_SHIELD_X,
	                                  GfxConstants.TURN_SHIELD_Y ) ); 
	    // insert in superclass figure list to ensure graphical
	    // rendering.
	    super.add(turnShieldIcon);
	    
	    produceField = new TextFigure("-",new Point(GfxConstants.CITY_PRODUCTION_X, GfxConstants.CITY_PRODUCTION_Y));
	    super.add(produceField);
	    balanceField = new TextFigure("-",new Point(GfxConstants.WORKFORCEFOCUS_X, GfxConstants.WORKFORCEFOCUS_Y));
	    super.add(balanceField);
	    moveCountField = new TextFigure("-", new Point(GfxConstants.UNIT_COUNT_X, GfxConstants.UNIT_COUNT_Y));
	    super.add(moveCountField);
	  }
}
